package com.skyyan.netty.jjf.util;

/**
 * BCD (Binary Coded Decimal) 编码解码工具类
 *
 * BCD格式：每个字节存储两个十进制数字
 * 例如：数字123456 -> BCD字节数组 [0x12, 0x34, 0x56]
 * @author skyyan
 */
public class BcdUtil {

    /**
     * 将十进制数字字符串转换为BCD字节数组
     * @param decimalStr 十进制数字字符串（只能包含0-9）
     * @param targetLength 目标字节数组长度
     * @return BCD字节数组
     * @throws IllegalArgumentException 如果输入包含非数字字符或长度超出限制
     */
    public static byte[] stringToBcd(String decimalStr, int targetLength) {
        if (decimalStr == null) {
            decimalStr = "";
        }

        // 移除所有非数字字符
        decimalStr = decimalStr.replaceAll("[^0-9]", "");

        // 检查长度限制（每个字节可存储2个数字）
        int maxDigits = targetLength * 2;
        if (decimalStr.length() > maxDigits) {
            throw new IllegalArgumentException(
                String.format("数字字符串长度 %d 超出BCD字节数组容量 %d（最多%d位数字）",
                            decimalStr.length(), targetLength, maxDigits));
        }

        // 左侧补0到偶数长度
        if (decimalStr.length() % 2 != 0) {
            decimalStr = "0" + decimalStr;
        }

        // 左侧补0到目标长度
        while (decimalStr.length() < maxDigits) {
            decimalStr = "0" + decimalStr;
        }

        byte[] bcdBytes = new byte[targetLength];

        for (int i = 0; i < targetLength; i++) {
            int startIndex = i * 2;
            int highNibble = Character.getNumericValue(decimalStr.charAt(startIndex));
            int lowNibble = Character.getNumericValue(decimalStr.charAt(startIndex + 1));

            if (highNibble < 0 || highNibble > 9 || lowNibble < 0 || lowNibble > 9) {
                throw new IllegalArgumentException("BCD编码只支持0-9的数字字符");
            }

            bcdBytes[i] = (byte) ((highNibble << 4) | lowNibble);
        }

        return bcdBytes;
    }

    /**
     * 将BCD字节数组转换为十进制数字字符串
     * @param bcdBytes BCD字节数组
     * @return 十进制数字字符串
     */
    public static String bcdToString(byte[] bcdBytes) {
        if (bcdBytes == null || bcdBytes.length == 0) {
            return "0";
        }

        StringBuilder sb = new StringBuilder();

        for (byte bcdByte : bcdBytes) {
            int highNibble = (bcdByte >> 4) & 0x0F;
            int lowNibble = bcdByte & 0x0F;

            // 验证BCD有效性（每个半字节应该在0-9范围内）
            if (highNibble > 9 || lowNibble > 9) {
                throw new IllegalArgumentException(
                    String.format("无效的BCD字节: 0x%02X (高位=%d, 低位=%d)",
                                bcdByte & 0xFF, highNibble, lowNibble));
            }

            sb.append(highNibble).append(lowNibble);
        }

        // 移除前导零（但保留至少一个数字）
        String result = sb.toString().replaceFirst("^0+", "");
        return result.isEmpty() ? "0" : result;
    }

    public static String bcdToStringNoRemoveZeros(byte[] bcdBytes) {
        if (bcdBytes == null || bcdBytes.length == 0) {
            return "0";
        }

        StringBuilder sb = new StringBuilder();

        for (byte bcdByte : bcdBytes) {
            int highNibble = (bcdByte >> 4) & 0x0F;
            int lowNibble = bcdByte & 0x0F;

            // 验证BCD有效性（每个半字节应该在0-9范围内）
            if (highNibble > 9 || lowNibble > 9) {
                throw new IllegalArgumentException(
                        String.format("无效的BCD字节: 0x%02X (高位=%d, 低位=%d)",
                                bcdByte & 0xFF, highNibble, lowNibble));
            }

            sb.append(highNibble).append(lowNibble);
        }

        // 移除前导零（但保留至少一个数字）
        String result = sb.toString();
        return result.isEmpty() ? "0" : result;
    }

    /**
     * 将整数转换为BCD字节数组
     * @param value 整数值
     * @param targetLength 目标字节数组长度
     * @return BCD字节数组
     */
    public static byte[] intToBcd(int value, int targetLength) {
        if (value < 0) {
            throw new IllegalArgumentException("BCD编码不支持负数: " + value);
        }

        return stringToBcd(String.valueOf(value), targetLength);
    }

    /**
     * 将BCD字节数组转换为整数
     * @param bcdBytes BCD字节数组
     * @return 整数值
     * @throws NumberFormatException 如果转换后的数字超出int范围
     */
    public static int bcdToInt(byte[] bcdBytes) {
        String decimalStr = bcdToString(bcdBytes);
        try {
            return Integer.parseInt(decimalStr);
        } catch (NumberFormatException e) {
            throw new NumberFormatException("BCD转换的数字超出int范围: " + decimalStr);
        }
    }

    /**
     * 验证字节数组是否为有效的BCD格式
     * @param bcdBytes 待验证的字节数组
     * @return true表示有效，false表示无效
     */
    public static boolean isValidBcd(byte[] bcdBytes) {
        if (bcdBytes == null) {
            return false;
        }

        try {
            for (byte bcdByte : bcdBytes) {
                int highNibble = (bcdByte >> 4) & 0x0F;
                int lowNibble = bcdByte & 0x0F;

                if (highNibble > 9 || lowNibble > 9) {
                    return false;
                }
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 格式化BCD字节数组为可读的十六进制字符串（用于调试）
     * @param bcdBytes BCD字节数组
     * @return 格式化的字符串，例如："12 34 56"
     */
    public static String formatBcdForDebug(byte[] bcdBytes) {
        if (bcdBytes == null || bcdBytes.length == 0) {
            return "[]";
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bcdBytes.length; i++) {
            if (i > 0) {
                sb.append(" ");
            }
            sb.append(String.format("%02X", bcdBytes[i] & 0xFF));
        }
        return sb.toString();
    }

    public static void main(String[] args) throws Exception{
        String str="9885250827182420";
        byte[] dd=BcdUtil.stringToBcd(str, 8);
        System.out.println(BcdUtil.bcdToString(dd));
    }
}

